package com.yict.csms.system.service.impl;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.annotation.Resource;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.yict.common.entity.PageEntity;
import com.yict.common.service.impl.BaseServiceImpl;
import com.yict.csms.company.dao.impl.ContractDaoImpl;
import com.yict.csms.system.dao.ICostProfessionDao;
import com.yict.csms.system.dao.IProfessionDao;
import com.yict.csms.system.entity.CostProfession;
import com.yict.csms.system.entity.DataDict;
import com.yict.csms.system.entity.Profession;
import com.yict.csms.system.service.IDataDictService;
import com.yict.csms.system.service.IProfessionService;
import com.yict.csms.system.util.DictionaryUtils;

@Service("professionService")
public class ProfessionServiceImpl extends
		BaseServiceImpl<Profession, Long, IProfessionDao> implements
		IProfessionService {
	private static Log logger = LogFactory.getLog(ProfessionServiceImpl.class);
	private IDataDictService dictService;
	private ContractDaoImpl contractDao;
	private ICostProfessionDao costProfessionDao;

	/**
	 * 列表查询界面
	 */
	public List<Profession> list(Map<String, Object> queryMap, PageEntity page,
			LinkedHashMap<String, Boolean> orderList) {
		List<Profession> list = new ArrayList<Profession>();
		Map<String, Object> map = new HashMap<String, Object>();
		StringBuilder hql = new StringBuilder("from Profession t where 1=1 ");
		String profecode = (String) queryMap.get("profecode");
		if (profecode != null && profecode.length() > 0) {
			map.put("profecode", "%" + profecode.toUpperCase() + "%");
			hql.append(" and upper(t.profecode) like :profecode");
		}
		String profename = (String) queryMap.get("profename");
		if (profename != null && profename.length() > 0) {
			map.put("profename", "%" + profename.toUpperCase() + "%");
			hql.append(" and upper(t.profename) like :profename");
		}
		String accountmethod = (String) queryMap.get("accountmethod");
		if (accountmethod != null && accountmethod.length() > 0) {
			map.put("accountmethod", accountmethod);
			hql.append(" and t.accountmethod = :accountmethod");
		}
		String commitstutas = (String) queryMap.get("commitstutas");
		if (commitstutas != null && commitstutas.length() > 0) {
			map.put("commitstutas", commitstutas);
			hql.append(" and t.commitstutas = :commitstutas");
		}
		String profetype = (String) queryMap.get("profetype");
		if (profetype != null && profetype.length() > 0) {
			map.put("profetype", profetype);
			hql.append(" and t.profetype = :profetype");
		}

		int count = this.getBaseDao().queryCount(
				"select count(*) " + hql.toString(), map);
		int firstrow = 0;
		int maxrows = 0;
		if (page != null) {
			page.setTotalRecord(count);
			firstrow = (page.getToPage() - 1) * page.getPageSize();
			maxrows = page.getPageSize();
		}
		if (count > 0) {
			if (orderList == null) {
				orderList = new LinkedHashMap<String, Boolean>();
			}
			if (orderList.size() == 0)
				orderList.put("updatedate", false);
			StringBuilder orderString = new StringBuilder("");
			for (Map.Entry<String, Boolean> entry : orderList.entrySet()) {
				String key = entry.getKey();
				boolean value = entry.getValue();
				if (orderString.length() > 0)
					orderString.append(",");
				orderString.append(key);
				if (!value)
					orderString.append(" desc");
			}
			hql.append(" order by ").append(orderString);
			list = this.getBaseDao().list(hql.toString(), map, firstrow,
					maxrows);
		}
		return list;
	}
	
	/**
	 * 查询由合同在有效期内的工种
	 * 列表查询界面
	 */
	public List<Profession> listByType(Long companyid,Date contractDate,String type){
		String hql = "from Profession t inner join t.contractRateSet c where c.contract.effectiveDate < :contractDate" +
				" and c.contract.expirationDate > :contractDate and c.contract.company.companyId = :companyid" +
				" and t.profetype = :profetype";
		Map<String,Object> map = new HashMap<String, Object>();
		map.put("contractDate", contractDate);
		map.put("companyid", companyid);
		map.put("profetype", type);
		
		List<Profession> list = this.getBaseDao().list(hql, map, 0, 0);
		
		return list;
	}
	
	/**
	 * 查询某个公司在指定日期有合同的工种
	 * @param companyid 公司主键
	 * @param contractDate 合同日期
	 * @return
	 */
	public List<Profession> queryByCompany(Long companyid,Date contractDate){
		List<Profession> list = new ArrayList<Profession>();
		try {
			list = this.getBaseDao().queryByCompany(companyid, contractDate);
		} catch (Exception e) {
			logger.warn(e);
			e.printStackTrace();
		}
		return list;
	}

	@Override
	public Profession findById(Long id) {
		Profession vo = super.findById(id);
		Set<CostProfession> set = vo.getCostProfessionCost();
		for(CostProfession cp : set){
			cp.getOrderProfeid().getProfeid();
		}
		return vo;
	}
	
	/**
	 * 根据id查找实体
	 * @param ids
	 * @return
	 */
	public List<Profession> listByIds(Collection<Long> ids){
		if(ids == null || ids.size() == 0) return new ArrayList<Profession>();
		String hql = "from Profession t where profeid in (:ids)";
		Map<String,Object> map = new HashMap<String, Object>();
		map.put("ids", ids);
		return getBaseDao().list(hql,map, 0, 0);
	}

	@Override
	@Transactional(readOnly = false)
	public boolean remove(Long[] ids) throws Exception {
		for(Long id : ids){
			Profession vo = getBaseDao().findbyId(id);
			if(vo == null) 
				throw new Exception("操作目标数据不存在！");
			if(vo.getStationSet().size() > 0) 
				throw new Exception("该工种已经被岗位引用，不能删除！");
			DataDict dict = dictService.findByCode(DictionaryUtils.SUBMIT_STATUS_SUBMITED);
			if(dict.getDictid().equals(vo.getCommitstutas()))
				throw new Exception("已提交的数据不能删除");
			
			if(vo.getContractRateSet().size() > 0)
				throw new Exception("该工种已经被合同费率引用，不能删除！");
			
			Map<String,Object> map = new HashMap<String, Object>();
			map.put("costProfeid", vo);
			List<CostProfession> cplist = costProfessionDao.list(map, null, 0, 0);
			String[] cppk = new String[cplist.size()];
			for(int i = 0;i < cplist.size();i++){
				cppk[i] = cplist.get(i).getCpid();
			}
			costProfessionDao.remove(cppk);
		}
		try {
			super.remove(ids);
		} catch (RuntimeException e) {
			logger.warn(e);
			throw new Exception("可能有数据被其他数据引用");
		}
		return true;
	}

	/**
	 * 批量提交
	 */
	@Override
	@Transactional(readOnly = false,rollbackFor = {Exception.class})
	public boolean submit(Long[] ids) throws Exception {
		IProfessionDao dao = this.getBaseDao();
		int i = 1;
		for (Long id : ids) {
			Profession vo = dao.findbyId(id);
			DataDict dict = dictService
					.findByCode(DictionaryUtils.SUBMIT_STATUS_SUBMITED);
			if (dict == null)
				throw new Exception("查找数据字典已提交状态出错");
			if(dict.getDictid().equals(vo.getCommitstutas()))
				throw new Exception("所选第" + i + "条记录不是为提交状态");
			vo.setCommitstutas(dict.getDictid());
			i = i + 1;
			// dao.update(vo);
		}
		return true;
	}

	@Resource(name = "professionDao")
	public void setBaseDao(IProfessionDao baseDao) {
		super.setBaseDao(baseDao);
	}

	// 计费工种下拉Map
	@Override
	public LinkedHashMap<String, String> getProfessionSelectMap(String profecode) {
		StringBuilder hql = new StringBuilder("from Profession t where 1=1 ");
		Map<String, Object> map = new HashMap<String, Object>();
		if (profecode != null && !profecode.equals("")) {
			map.put("profecode", profecode);
			hql.append(" and t.profetype = (select b.dictid from DataDict b where b.datatype = 'PROFETYPE' and b.datacode =:profecode)");
		}
		hql.append(" and t.commitstutas = (select d.dictid from DataDict d where d.datatype = 'COMMITSTUTAS' and d.datacode = 'COMMITSTUTAS_1')");
		hql.append(" order by t.createdate");
		List<Profession> list = this.getBaseDao().list(hql.toString(), map, 0,
				0);

		LinkedHashMap<String, String> resultMap = new LinkedHashMap<String, String>();
		for (Profession profession : list) {
			resultMap.put(profession.getProfeid().toString(),
					profession.getProfename());
		}
		return resultMap;
	}

	// 计费方式下拉Map
	public LinkedHashMap<String, String> getAccountMethodSelectMap() {
		String hql = "from Profession p order by p.createdate";
		LinkedHashMap<String, String> map = new LinkedHashMap<String, String>();
		List<Profession> list = this.getBaseDao().list(hql, null, 0, 0);
		for (Profession profession : list) {
			map.put(profession.getProfeid().toString(),
					profession.getAccountmethod());
		}
		return map;
	}

	@Override
	@Transactional(readOnly = false)
	public boolean save(Profession t, Long parentId) throws Exception {
		if(this.findByCode(t.getProfecode()) != null) 
			throw new Exception("已经存在相同的工种编码");
		this.save(t);
		if(parentId != null && parentId > 0){
			Profession pvo = this.getBaseDao().findbyId(parentId);
			if(pvo == null) throw new Exception("没有找到上级工种！可能已经被删除");
			CostProfession mp = new CostProfession();
			mp.setCostProfeid(t);
			mp.setOrderProfeid(pvo);
			costProfessionDao.save(mp);
		}
		return true;
	}

	@Override
	@Transactional(readOnly = false)
	public boolean update(Profession t, Long parentId) throws Exception {
		Profession po = this.findByCode(t.getProfecode());
		if(po != null && !po.getProfeid().equals(t.getProfeid()))
			throw new Exception("已经存在相同的工种编码");
		Profession vo = this.findById(t.getProfeid());
		vo.setProfecode(t.getProfecode());
		vo.setProfename(t.getProfename());
		vo.setAccountmethod(t.getAccountmethod());
		vo.setProfetype(t.getProfetype());
		//vo.setCommitstutas(t.getCommitstutas());
		vo.setUpdatedate(t.getUpdatedate());
		vo.setUpdateperson(t.getUpdateperson());
		//this.update(t);
		
		Map<String,Object> map = new HashMap<String, Object>();
		map.put("costProfeid", t);
		List<CostProfession> cplist = costProfessionDao.list(map, null, 0, 0);
		if(cplist.size() > 1) {
			StringBuilder msg = new StringBuilder();
			for(CostProfession mpvo : cplist){
				msg.append("id为").append(mpvo.getOrderProfeid()).append("名称为").append(mpvo.getOrderProfeid().getProfename());
			}
			logger.warn("有超过一个工种" + msg + "被分解到工种" + t.getProfename());
		}
		
		if(parentId != null && parentId > 0){
			Profession pvo = this.getBaseDao().findbyId(parentId);
			if(pvo == null) throw new Exception("没有找到上级工种！可能已经被删除");
			if(pvo.getProfeid().equals(t.getProfeid())) throw new Exception("上级工种不能选择自己");
			CostProfession mp;
			if(cplist.size() == 0){
				mp = new CostProfession();
				mp.setCostProfeid(t);
				mp.setOrderProfeid(pvo);
				costProfessionDao.save(mp);
			}else{
				mp = cplist.get(0);
				mp.setOrderProfeid(pvo);
			}
		}else{
			String[] cppk = new String[cplist.size()];
			for(int i = 0;i < cplist.size();i++){
				cppk[i] = cplist.get(i).getCpid();
			}
			costProfessionDao.remove(cppk);
		}
		return true;
	}
	
	/**
	 * 根据代码查找，如果有多个则随机返回一个
	 * @param code
	 * @return
	 */
	public Profession findByCode(String code){
		if(code == null || code.length() == 0) return null;
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("profecode", code);
		List<Profession> list = this.list(map, null, null);
		Profession vo = null;
		if(list.size() > 0) vo = list.get(0);
		return vo;
	}

	public IDataDictService getDictService() {
		return dictService;
	}

	@Resource(name = "dataDictService")
	public void setDictService(IDataDictService dictService) {
		this.dictService = dictService;
	}

	public ContractDaoImpl getContractDao() {
		return contractDao;
	}

	@Resource(name = "contractDaoImpl")
	public void setContractDao(ContractDaoImpl contractDao) {
		this.contractDao = contractDao;
	}

	public ICostProfessionDao getCostProfessionDao() {
		return costProfessionDao;
	}

	@Resource(name = "costProfessionDao")
	public void setCostProfessionDao(ICostProfessionDao costProfessionDao) {
		this.costProfessionDao = costProfessionDao;
	}
}
